﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Volo.Abp;

namespace Xms.Abp.Features;

public static class FeaturesHelper
{
    private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _featuresProperties = new();
    public static IDictionary<string, PropertyInfo> GetFeatureProperties<TSettings>()
    {
        var type = typeof(TSettings);
        return GetFeatureProperties(type);
    }
    public static IDictionary<string, PropertyInfo> GetFeatureProperties(Type type)
    {
        Check(type);
        if (!_featuresProperties.ContainsKey(type))
        {
            _featuresProperties[type] = type.GetProperties()
                .Where(w => (w.PropertyType.IsValueType || w.PropertyType == typeof(string)) && w.CanRead && w.GetCustomAttribute<FeatureIgnoreAttribute>() == null)
                .ToDictionary(r => r.Name);
        }
        return _featuresProperties[type];
    }
    public static void Check(Type type)
    {
        if (!typeof(IFeatures).IsAssignableFrom(type))
        {
            throw new AbpException($"Type '{type.FullName}' is invalid feature definition type.");
        }
    }
    public static Type GetLocalizationResource(Type type)
    {
        Check(type);
        return type.GetCustomAttribute<FeaturesDefinitionAttribute>().LocalizationResource;
    }

    public static string GetDisplayNameKey(Type type, string nameSpace = null, string propertyName = null)
    {
        Check(type);
        return "Features:" + (nameSpace.IsNullOrWhiteSpace() ? "" : ("." + nameSpace)) + type.Name.RemovePostFix("Features") + (propertyName.IsNullOrWhiteSpace() ? "" : ("." + propertyName)) + ".DisplayName";
    }

    public static string GetDescriptionKey(Type type, string nameSpace = null, string propertyName = null)
    {
        Check(type);
        return "Features:" + (nameSpace.IsNullOrWhiteSpace() ? "" : ("." + nameSpace)) + type.Name.RemovePostFix("Features") + (propertyName.IsNullOrWhiteSpace() ? "" : ("." + propertyName)) + ".Description";
    }

    public static string GetTypeName(Type type)
    {
        return type.Name.RemovePostFix("Features");
    }

    public static string GetFeatureName(Type type, string propertyName = null)
    {
        Check(type);
        return GetTypeName(type) + (propertyName.IsNullOrWhiteSpace() ? "" : ("." + propertyName));
    }

    public static string GetSubFeatureName(Type type, string nameSpace, string propertyName = null)
    {
        Check(type);
        return nameSpace + "." + GetTypeName(type) + (propertyName.IsNullOrWhiteSpace() ? "" : ("." + propertyName));
    }
}
